package com.bjtu.ptsite.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bjtu.ptsite.model.InviteCode;
import com.bjtu.ptsite.model.User;
import com.bjtu.ptsite.model.UserDTO;
import com.fasterxml.jackson.databind.ser.Serializers;
import org.apache.ibatis.annotations.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

/**
 *
 * @author Zehao Wang, Junjie Zhang, Yutao Wei
 *
 */
@Mapper
public interface UserMapper {
        String SELECT_FIELDS = " u.user_id,u.identification_number,u.avatar,u.username,u.level ";

        /**
         * 根据身份证号和密码查询用户信息，用于用户登录验证。
         *
         * @param user 包含身份证号和密码的用户对象
         * @return 匹配的用户对象，如果未找到则返回null
         */
        @Select("select * from user where identification_number=#{identificationNumber} and password=#{password}")
        User login(User user);

        /**
         * 根据用户名查询用户信息。
         *
         * @param username 要查询的用户名
         * @return 匹配的用户对象，如果未找到则返回null
         */
        @Select("SELECT * FROM user WHERE username = #{username}")
        User selectByUsername(String username);

        /**
         * 根据用户ID查询用户信息。
         *
         * @param userId 要查询的用户ID
         * @return 匹配的用户对象，如果未找到则返回null
         */
        @Select("SELECT * FROM user WHERE user_id = #{userId}")
        User selectById(int userId);

        /**
         * 根据邮箱查询用户信息。
         *
         * @param email 要查询的邮箱地址
         * @return 匹配的用户对象，如果未找到则返回null
         */
        @Select("SELECT * FROM user WHERE email = #{email}")
        User selectByEmail(String email);

        /**
         * 插入新用户信息，自动生成用户ID。
         *
         * @param user 要插入的用户对象，必须包含用户名、邮箱、密码等必要信息
         */
        @Insert("INSERT INTO user(username, email, password, registration_date, identification_number,pass_key,avatar) "
                        +
                        "VALUES(#{username}, #{email}, #{password}, #{registrationDate}, #{identificationNumber},#{passKey},#{avatar})")
        @Options(useGeneratedKeys = true, keyProperty = "userId")
        void insertUser(User user);

        /**
         * 选择性更新用户信息，只更新非空字段。
         *
         * @param user 包含要更新信息的用户对象，必须包含用户ID
         */
        @Update("<script>" +
                        "UPDATE user SET " +
                        "<if test='username != null'>username = #{username},</if>" +
                        "<if test='address != null'>address = #{address},</if>" +
                        "<if test='seedPoints != null'>seed_points = #{seedPoints},</if>" +
                        "<if test='uploadedDelta != null'>uploaded_delta = #{uploadedDelta},</if>" +
                        "<if test='dailyAward != null'>daily_award = #{dailyAward},</if>" +
                        "<if test='unactivateDay != null'>unactivate_day = #{unactivateDay},</if>" +
                        "<if test='uploadAssess != null'>upload_assess = #{uploadAssess},</if>" +
                        "<if test='assessDay != null'>assess_day = #{assessDay},</if>" +
                        "<if test='sharingRate != null'>sharing_rate = #{sharingRate} </if>" +
                        "WHERE user_id = #{userId}" +
                        "</script>")
        void updateUserSelective(User user);

        /**
         * 更新用户密码。
         *
         * @param userId      要更新密码的用户ID
         * @param newPassword 新密码
         */
        @Update("UPDATE user SET password = #{newPassword} WHERE user_id = #{userId}")
        void updatePassword(int userId, String newPassword);

        /**
         * 根据通行证密钥查询用户信息。
         *
         * @param passKey 要查询的通行证密钥
         * @return 匹配的用户对象，如果未找到则返回null
         */
        @Select("SELECT * FROM user WHERE pass_key = #{passKey}")
        User selectByPasskey(String passKey);

        /**
         * 后续可定时任务优化更新分享率
         * 
         * @param passKey
         * @param uploadedDelta
         * @param downloadedDelta
         * @param
         */
        @Update("UPDATE user SET uploaded_delta = uploaded_delta + #{uploadedDelta}," +
                        "upload_assess = upload_assess + #{uploadedDelta}," +
                        "downloaded_delta = downloaded_delta + #{downloadedDelta}  " +
                        " WHERE pass_key = #{passKey}")
        void updateUserTraffic(String passKey, long uploadedDelta, long downloadedDelta);

        /**
         * 根据身份证号查询用户信息。
         *
         * @param identificationNumber 要查询的身份证号
         * @return 匹配的用户对象，如果未找到则返回null
         */
        @Select("SELECT * FROM user WHERE identification_number = #{identificationNumber}")
        User selectByIdentificationNumber(Integer identificationNumber);

        /**
         * 更新用户头像。
         *
         * @param user 包含用户ID和新头像信息的用户对象
         */
        @Update("UPDATE user SET avatar = #{avatar} WHERE user_id = #{userId}")
        void updateAvatar(User user);

        /**
         * 根据用户ID查询用户头像。
         *
         * @param userId 要查询的用户ID
         * @return 用户头像信息，如果未找到则返回null
         */
        @Select("SELECT avatar FROM user WHERE user_id = #{userId}")
        String selectAvatarById(int userId);

        /**
         * 更新用户积分和上传量。
         *
         * @param user 包含用户ID、积分和上传量的用户对象
         */
        @Update("UPDATE user SET seed_points = #{seedPoints}, uploadgb = #{uploadGB} WHERE user_id = #{userId}")
        void updateUserPoints(User user);

        /**
         * 获取指定用户关注的用户列表
         * 
         * @param userId 用户ID
         * @return 关注的用户DTO列表
         */
        @Select("Select" + SELECT_FIELDS
                        + "FROM user AS u,follow As f WHERE f.follow_id = #{userId} AND u.user_id = f.followed_id")
        List<UserDTO> getFollows(int userId);

        /**
         * 获取指定用户的粉丝列表
         * 
         * @param userId 用户ID
         * @return 粉丝用户DTO列表
         */
        @Select("Select" + SELECT_FIELDS
                        + "FROM user AS u,follow As f WHERE f.followed_id = #{userId} AND u.user_id = f.follow_id")
        List<UserDTO> getFans(int userId);

        /**
         * 增加用户的关注数
         * 
         * @param userId 用户ID
         */
        @Update("UPDATE user SET follows = follows+1 WHERE user_id = #{userId}")
        void addFollows(int userId);

        /**
         * 增加用户的粉丝数
         * 
         * @param userId 用户ID
         */
        @Update("UPDATE user SET fans = fans+1 WHERE user_id = #{userId}")
        void addFans(int userId);

        /**
         * 减少用户的关注数
         * 
         * @param userId 用户ID
         */
        @Update("UPDATE user SET follows = follows-1 WHERE user_id = #{userId}")
        void deFollows(int userId);

        /**
         * 减少用户的粉丝数
         * 
         * @param userId 用户ID
         */
        @Update("UPDATE user SET fans = fans-1 WHERE user_id = #{userId}")
        void deFans(int userId);

        /**
         * 查找分享率达到或超过指定阈值的用户
         * 
         * @param threshold 分享率阈值
         * @return 符合条件的用户列表
         */
        @Select("SELECT * FROM user WHERE sharing_rate>=#{threshold}")
        List<User> findQualified(double threshold);

        /**
         * 更新用户等级
         * 
         * @param userId   用户ID
         * @param newLevel 新等级
         */
        @Update("UPDATE user SET level = #{newLevel} WHERE user_id = #{userId}")
        void updateLevel(int userId, int newLevel);

        /**
         * 封禁用户
         * 
         * @param userId 用户ID
         */
        @Update("UPDATE user SET is_baned = 1 WHERE user_id = #{userId}")
        void banUser(int userId);

        /**
         * 解封用户
         * 
         * @param userId 用户ID
         */
        @Update("UPDATE user SET is_baned = 0 WHERE user_id = #{userId}")
        void unbanUser(int userId);

        /**
         * 后续可定时任务优化更新分享率
         * 
         * @param user 用户对象
         */
        @Update("UPDATE user SET " +
                        "seed_points = #{seedPoints} WHERE pass_key = #{passKey}")
        void updateUserTraffic1(User user);

        /**
         * 更新用户流量
         * 
         * @param id 用户对象的id
         */
        @Delete("DELETE FROM user WHERE user_id = #{id}")
        void delete(int id);

        /**
         * 获取用户总数
         * @return 用户总数
         */
        @Select("SELECT COUNT(*) FROM user")
        int selectTotalCount();

        /**
         * 分页查询用户
         * @param offset 偏移量
         * @param size 每页大小
         * @return 用户列表
         */
        @Select("SELECT * FROM user LIMIT #{size} OFFSET #{offset}")
        List<User> selectUsersByPage(int offset, int size);

        /**
         * 查询所有用户
         * @return 用户列表
         */
        @Select("SELECT * FROM user")
        List<User> selectUserALL();
}
